﻿using NLog;
using Prism.Commands;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading;
using System.Threading.Tasks;
using System.Xml.Linq;
using ViewROI;
using GeneralMotionControlProject.WPF;
using HalconDotNet;
using ModuleBase;
using Prism.Ioc;
using MessageBox = System.Windows.Forms.MessageBox;
using Newtonsoft.Json;
using GeneralMotionControlProject.WPF.Extensions;
using GeneralMotionControlProject.Vision.Services;

namespace HostComputerPlatform.ViewModels
{
    public class CameraCalibDialogViewModel : DialogViewModel
    {
        #region 变量
        private readonly IDrawROI drawROI;
        private CancellationTokenSource source0, source1;
        private static Logger logger = LogManager.GetCurrentClassLogger();

        private int handIndex = 0; private string handDir = string.Empty;
        private readonly IHIKCameraService leftCamera;
        private bool isClosing = false;
        #endregion
        #region 属性
        private HImage cameraImage0;
        public HImage CameraImage0
        {
            get { return cameraImage0; }
            set { SetProperty(ref cameraImage0, value); }
        }
        private bool cameraRepaint0;
        public bool CameraRepaint0
        {
            get { return cameraRepaint0; }
            set { SetProperty(ref cameraRepaint0, value); }
        }
        private ObservableCollection<ROI> cameraROIList0 = new ObservableCollection<ROI>();
        public ObservableCollection<ROI> CameraROIList0
        {
            get { return cameraROIList0; }
            set { SetProperty(ref cameraROIList0, value); }
        }
        private HObject cameraAppendHObject0;
        public HObject CameraAppendHObject0
        {
            get { return cameraAppendHObject0; }
            set { SetProperty(ref cameraAppendHObject0, value); }
        }
        private HMsgEntry cameraAppendHMessage0;
        public HMsgEntry CameraAppendHMessage0
        {
            get { return cameraAppendHMessage0; }
            set { SetProperty(ref cameraAppendHMessage0, value); }
        }
        private Tuple<string, object> cameraGCStyle0;
        public Tuple<string, object> CameraGCStyle0
        {
            get { return cameraGCStyle0; }
            set { SetProperty(ref cameraGCStyle0, value); }
        }
        private bool isBusy;
        public bool IsBusy
        {
            get { return isBusy; }
            set { SetProperty(ref isBusy, value); }
        }
        private double cameraExposureTime;
        public double CameraExposureTime
        {
            get { return cameraExposureTime; }
            set { SetProperty(ref cameraExposureTime, value); }
        }
        private bool isDrawing;
        public bool IsDrawing
        {
            get { return isDrawing; }
            set { SetProperty(ref isDrawing, value); }
        }
        private double leftCameraCalibDist;
        public double LeftCameraCalibDist
        {
            get { return leftCameraCalibDist; }
            set { SetProperty(ref leftCameraCalibDist, value); }
        }
        private double vcxyLimit;
        public double VxyLimit
        {
            get { return vcxyLimit; }
            set { SetProperty(ref vcxyLimit, value); }
        }
        #endregion
        #region 命令
        private DelegateCommand<object> cameraOperateCommand;
        public DelegateCommand<object> CameraOperateCommand =>
            cameraOperateCommand ?? (cameraOperateCommand = new DelegateCommand<object>(ExecuteCameraOperateCommand));
        private DelegateCommand calcCalibCommand;
        public DelegateCommand CalcCalibCommand =>
            calcCalibCommand ?? (calcCalibCommand = new DelegateCommand(ExecuteCalcCalibCommand));
        private DelegateCommand createShapeModelCommand;
        public DelegateCommand CreateShapeModelCommand =>
            createShapeModelCommand ?? (createShapeModelCommand = new DelegateCommand(ExecuteCreateShapeModelCommand));
        private DelegateCommand findShapeModelCommand;
        public DelegateCommand FindShapeModelCommand =>
            findShapeModelCommand ?? (findShapeModelCommand = new DelegateCommand(ExecuteFindShapeModelCommand));
        private DelegateCommand<object> liveGrabCommand;
        public DelegateCommand<object> LiveGrabCommand =>
            liveGrabCommand ?? (liveGrabCommand = new DelegateCommand<object>(ExecuteLiveGrabCommand));
        private DelegateCommand createLaserCenterCommand;
        public DelegateCommand CreateLaserCenterCommand =>
            createLaserCenterCommand ?? (createLaserCenterCommand = new DelegateCommand(ExecuteCreateLaserCenterCommand));
        private DelegateCommand<object> textBoxLostFocusCommand;
        public DelegateCommand<object> TextBoxLostFocusCommand =>
            textBoxLostFocusCommand ?? (textBoxLostFocusCommand = new DelegateCommand<object>(ExecuteTextBoxLostFocusCommand));

        void ExecuteTextBoxLostFocusCommand(object obj)
        {
            var mdb = containerProvider.Resolve<MDbContext>();
            switch (obj.ToString())
            {
                case "CameraExposureTime":
                    {
                        var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "CameraExposureTime" && m.Hand == handIndex);
                        if (_mParam != null)
                        {
                            _mParam.Value = CameraExposureTime.ToString("f1");
                            mdb.SaveChanges();
                        }
                    }
                    break;
                case "VxyLimit":
                    {
                        var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "VxyLimit" && m.Hand == handIndex);
                        if (_mParam != null)
                        {
                            _mParam.Value = VxyLimit.ToString("f1");
                            mdb.SaveChanges();
                        }
                    }
                    break;
                case "LeftCameraCalibDist":
                    {
                        Properties.Settings.Default.LeftCameraCalibDist = LeftCameraCalibDist;
                        Properties.Settings.Default.Save();
                    }
                    break;
                default:
                    break;
            }
        }
        void ExecuteCreateLaserCenterCommand()
        {
            if (CameraImage0 != null)
            {
                if (MessageBox.Show("确认要画激光中心位置吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
                {
                    try
                    {
                        IsDrawing = true;
                        var roi = drawROI.ImageViewer1.DrawROI(ROI.ROI_TYPE_CIRCLE);
                        IsDrawing = false;
                        if (!isClosing)
                        {
                            var region = roi.getRegion();

                            HOperatorSet.RegionFeatures(region, "row", out var RefRow);
                            HOperatorSet.RegionFeatures(region, "column", out var RefColumn);

                            CameraAppendHObject0 = null;
                            CameraGCStyle0 = new Tuple<string, object>("Color", "turquoise");
                            CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");

                            HOperatorSet.GenCrossContourXld(out var cross1, RefRow, RefColumn, 24, 0);
                            CameraAppendHObject0 = cross1;

                            region.Dispose();

                            OffsetPixel op = JsonConvert.DeserializeObject<OffsetPixel>(Properties.Settings.Default.LeftCalibOffsetPixel);
                            if (op != null)
                            {
                                op.Row1 = Math.Round(RefRow.D, 1);
                                op.Column1 = Math.Round(RefColumn.D, 1);
                            }
                            else
                            {
                                op = new OffsetPixel
                                {
                                    Row0 = Math.Round(RefRow.D, 1),
                                    Column0 = Math.Round(RefColumn.D, 1),
                                    Row1 = Math.Round(RefRow.D, 1),
                                    Column1 = Math.Round(RefColumn.D, 1)
                                };
                            }
                            switch (handIndex)
                            {
                                case 0:
                                    Properties.Settings.Default.LeftCalibOffsetPixel = JsonConvert.SerializeObject(op);
                                    Properties.Settings.Default.Save();
                                    break;
                                default:
                                    break;
                            }
                        }


                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            else
            {
                MessageBox.Show("图像不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        void ExecuteLiveGrabCommand(object isLiveGrab)
        {
            if ((bool)isLiveGrab)
            {
                source1 = new CancellationTokenSource();
                CancellationToken token = source1.Token;
                Task.Run(() => ContinueGrab(token), token);
                IsBusy = true;
            }
            else
            {
                if (source1 != null)
                {
                    source1.Cancel();
                }
                IsBusy = false;
            }
        }
        void ExecuteFindShapeModelCommand()
        {
            if (CameraImage0 != null)
            {
                try
                {
                    string dirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}");
                    HTuple ModelID;
                    HOperatorSet.ReadShapeModel(System.IO.Path.Combine(System.Environment.CurrentDirectory, dirPath, $"CalibShapeModelID.shm"), out ModelID);
                    HTuple Row, Column, Angle, Score;
                    HOperatorSet.FindShapeModel(CameraImage0, ModelID, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), 0.3, 0, 0.5, "least_squares", new HTuple(5).TupleConcat(1), 0.75, out Row, out Column, out Angle, out Score);
                    HOperatorSet.ClearShapeModel(ModelID);
                    CameraAppendHMessage0 = null;
                    CameraAppendHObject0 = null;

                    CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                    if (Score.TupleLength() > 0)
                    {
                        for (int i = 0; i < Score.TupleLength(); i++)
                        {
                            HTuple HomMat2D;
                            HOperatorSet.HomMat2dIdentity(out HomMat2D);
                            HOperatorSet.HomMat2dRotate(HomMat2D, Angle.TupleSelect(i), 0, 0, out HomMat2D);
                            HOperatorSet.HomMat2dTranslate(HomMat2D, Row.TupleSelect(i), Column.TupleSelect(i), out HomMat2D);
                            HTuple hv_DxfStatus; HObject ModelContours;
                            HOperatorSet.ReadContourXldDxf(out ModelContours, System.IO.Path.Combine(dirPath, $"CalibShapeModelContours.dxf"), new HTuple(), new HTuple(), out hv_DxfStatus);
                            HObject TransContours;
                            HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);
                            CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                            CameraAppendHObject0 = TransContours;


                            OffsetPixel op = JsonConvert.DeserializeObject<OffsetPixel>(Properties.Settings.Default.LeftCalibOffsetPixel);
                            double _offsetRow = 0, _offsetColumn = 0;
                            if (op != null)
                            {
                                _offsetRow = op.Row1 - op.Row0;
                                _offsetColumn = op.Column1 - op.Column0;
                            }
                            CameraGCStyle0 = new Tuple<string, object>("Color", "turquoise");
                            HOperatorSet.GenCrossContourXld(out var cross1, Row.TupleSelect(i) + _offsetRow, Column.TupleSelect(i) + _offsetColumn, 24, 0);
                            CameraAppendHObject0 = cross1;
                        }
                    }
                    else
                    {
                        MessageBox.Show("未来找到模板", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                MessageBox.Show("图像不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        void ExecuteCreateShapeModelCommand()
        {
            if (CameraImage0 != null)
            {
                if (MessageBox.Show("确认要创建模板吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
                {
                    string dirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}");
                    try
                    {
                        IsDrawing = true;
                        var roi = drawROI.ImageViewer1.DrawROI(ROI.ROI_TYPE_REGION);
                        IsDrawing = false;
                        if (!isClosing)
                        {
                            HRegion ModelRegion = roi.getRegion();
                            HObject TemplateImage;
                            HOperatorSet.ReduceDomain(CameraImage0, ModelRegion, out TemplateImage);
                            HTuple ModelID;
                            HOperatorSet.CreateShapeModel(TemplateImage, 3, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), new HTuple(1).TupleRad(), new HTuple("none").TupleConcat("no_pregeneration"), "use_polarity", new HTuple(30).TupleConcat(30).TupleConcat(0), 10, out ModelID);
                            HObject ModelContours;
                            HOperatorSet.GetShapeModelContours(out ModelContours, ModelID, 1);
                            HTuple ModelRegionArea, RefRow, RefColumn;
                            HOperatorSet.AreaCenter(ModelRegion, out ModelRegionArea, out RefRow, out RefColumn);
                            HTuple HomMat2D;
                            HOperatorSet.VectorAngleToRigid(0, 0, 0, RefRow, RefColumn, 0, out HomMat2D);
                            HObject TransContours;
                            HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);
                            CameraAppendHObject0 = null;
                            CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                            CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                            CameraAppendHObject0 = TransContours;
                            CameraAppendHMessage0 = null;
                            CameraAppendHMessage0 = new HMsgEntry($"坐标:{RefRow.D:F1},{RefColumn.D:F1}", 100, 100);
                            HOperatorSet.WriteShapeModel(ModelID, System.IO.Path.Combine(dirPath, "CalibShapeModelID.shm"));
                            HOperatorSet.ClearShapeModel(ModelID);
                            HOperatorSet.WriteContourXldDxf(ModelContours, System.IO.Path.Combine(dirPath, "CalibShapeModelContours.dxf"));


                            OffsetPixel op = JsonConvert.DeserializeObject<OffsetPixel>(Properties.Settings.Default.LeftCalibOffsetPixel);
                            if (op != null)
                            {
                                op.Row0 = Math.Round(RefRow.D, 1);
                                op.Column0 = Math.Round(RefColumn.D, 1);
                            }
                            else
                            {
                                op = new OffsetPixel
                                {
                                    Row0 = Math.Round(RefRow.D, 1),
                                    Column0 = Math.Round(RefColumn.D, 1),
                                    Row1 = Math.Round(RefRow.D, 1),
                                    Column1 = Math.Round(RefColumn.D, 1)
                                };
                            }
                            switch (handIndex)
                            {
                                case 0:
                                    Properties.Settings.Default.LeftCalibOffsetPixel = JsonConvert.SerializeObject(op);
                                    Properties.Settings.Default.Save();
                                    break;
                                default:
                                    break;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            }
            else
            {
                MessageBox.Show("图像不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        void ExecuteCalcCalibCommand()
        {
            if (CameraImage0 != null)
            {
                if (MessageBox.Show("确认要计算标定吗？", "确认", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
                {
                    try
                    {
                        string dirPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}");
                        string filepath_image = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}\\images");
                        OffsetPixel op;
                        double dist;
                        switch (handIndex)
                        {
                            case 0:
                            default:
                                {
                                    dist = Properties.Settings.Default.LeftCameraCalibDist;
                                    op = JsonConvert.DeserializeObject<OffsetPixel>(Properties.Settings.Default.LeftCalibOffsetPixel);
                                }
                                break;
                        }
                        double _offsetRow = 0, _offsetColumn = 0;
                        if (op != null)
                        {
                            _offsetRow = op.Row1 - op.Row0;
                            _offsetColumn = op.Column1 - op.Column0;
                        }
                        double[][] diffArray = new double[9][]
                       { new double[]{ 0,0,0},
                                     new double[]{ dist * 1, 0,0} ,
                                     new double[]{ dist * 1, dist * 1,0},
                                     new double[]{ 0, dist * 1,0},
                                     new double[]{ dist * -1 , dist * 1,0},
                                     new double[]{ dist * -1,0,0},
                                     new double[]{ dist * -1, dist * -1,0},
                                     new double[]{ 0, dist * -1,0},
                                     new double[]{ dist * 1, dist * -1,0}};
                        double[][] Array1 = new double[9][];

                        HOperatorSet.ReadShapeModel(System.IO.Path.Combine(dirPath, $"CalibShapeModelID.shm"), out var ModelID);
                        HOperatorSet.ReadContourXldDxf(out var ModelContours, System.IO.Path.Combine(dirPath, $"CalibShapeModelContours.dxf"), new HTuple(), new HTuple(), out var hv_DxfStatus);
                        HTuple Row, Column, Angle, Score;
                        HOperatorSet.FindShapeModel(CameraImage0, ModelID, new HTuple(-180).TupleRad(), new HTuple(360).TupleRad(), 0.3, 0, 0.5, "least_squares", new HTuple(5).TupleConcat(1), 0.75, out Row, out Column, out Angle, out Score);
                        HOperatorSet.ClearShapeModel(ModelID);

                        CameraAppendHMessage0 = null;
                        CameraAppendHObject0 = null;

                        if (Score.TupleLength() == 9)
                        {
                            CameraGCStyle0 = new Tuple<string, object>("DrawMode", "margin");
                            List<Tuple<HTuple, HTuple, HTuple>> _list0 = new List<Tuple<HTuple, HTuple, HTuple>>();
                            for (int i = 0; i < 9; i++)
                            {
                                _list0.Add(new Tuple<HTuple, HTuple, HTuple>(Row.TupleSelect(i), Column.TupleSelect(i), Angle.TupleSelect(i)));
                            }

                            var rowMax = Row.DArr.Max();
                            var rowMin = Row.DArr.Min();
                            var rowGap = (rowMax - rowMin) / 4;
                            var columnMax = Column.DArr.Max();
                            var columnMin = Column.DArr.Min();
                            var columnGap = (columnMax - columnMin) / 4;

                            List<Tuple<HTuple, HTuple, HTuple>> _list1 = new List<Tuple<HTuple, HTuple, HTuple>>();

                            var p0 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap && item.Item1 < rowMin + rowGap * 3
                                                && item.Item2 > columnMin + columnGap && item.Item2 < columnMin + columnGap * 3);
                            _list1.Add(p0);

                            var p1 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap && item.Item1 < rowMin + rowGap * 3
                                                && item.Item2 > columnMin + columnGap * 3);
                            _list1.Add(p1);

                            var p2 = _list0.FirstOrDefault(item => item.Item1 < rowMin + rowGap
                                                && item.Item2 > columnMin + columnGap * 3);
                            _list1.Add(p2);

                            var p3 = _list0.FirstOrDefault(item => item.Item1 < rowMin + rowGap
                                                && item.Item2 > columnMin + columnGap && item.Item2 < columnMin + columnGap * 3);
                            _list1.Add(p3);

                            var p4 = _list0.FirstOrDefault(item => item.Item1 < rowMin + rowGap
                                                && item.Item2 < columnMin + columnGap);
                            _list1.Add(p4);

                            var p5 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap && item.Item1 < rowMin + rowGap * 3
                                                && item.Item2 < columnMin + columnGap);
                            _list1.Add(p5);

                            var p6 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap * 3
                                                && item.Item2 < columnMin + columnGap);
                            _list1.Add(p6);

                            var p7 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap * 3
                                                && item.Item2 > columnMin + columnGap && item.Item2 < columnMin + columnGap * 3);
                            _list1.Add(p7);

                            var p8 = _list0.FirstOrDefault(item => item.Item1 > rowMin + rowGap * 3
                                                && item.Item2 > columnMin + columnGap * 3);
                            _list1.Add(p8);

                            var arr1 = _list1.ToArray();
                            for (int i = 0; i < 9; i++)
                            {
                                HTuple HomMat2D;
                                HOperatorSet.HomMat2dIdentity(out HomMat2D);
                                HOperatorSet.HomMat2dRotate(HomMat2D, arr1[i].Item3, 0, 0, out HomMat2D);
                                HOperatorSet.HomMat2dTranslate(HomMat2D, arr1[i].Item1, arr1[i].Item2, out HomMat2D);

                                HObject TransContours;
                                HOperatorSet.AffineTransContourXld(ModelContours, out TransContours, HomMat2D);


                                Array1[i] = new double[4] { (arr1[i].Item1 + _offsetRow).D, (arr1[i].Item2 + _offsetColumn).D, 0 + diffArray[i][0], 0 + diffArray[i][1] };


                                CameraGCStyle0 = new Tuple<string, object>("Color", "green");
                                CameraAppendHObject0 = TransContours;

                                CameraAppendHMessage0 = new HMsgEntry($"{i + 1}", (int)(arr1[i].Item1 + _offsetRow - 5).D, (int)(arr1[i].Item2 + _offsetColumn + 5).D);

                                CameraGCStyle0 = new Tuple<string, object>("Color", "turquoise");
                                HOperatorSet.GenCrossContourXld(out var cross1, Row + _offsetRow, Column + _offsetColumn, 24, 0);
                                CameraAppendHObject0 = cross1;
                            }

                        }

                        HOperatorSet.VectorToHomMat2d(new HTuple(Array1[0][0]).TupleConcat(Array1[1][0]).TupleConcat(Array1[2][0]).TupleConcat(Array1[3][0]).TupleConcat(Array1[4][0]).TupleConcat(Array1[5][0]).TupleConcat(Array1[6][0]).TupleConcat(Array1[7][0]).TupleConcat(Array1[8][0]),
                                                        new HTuple(Array1[0][1]).TupleConcat(Array1[1][1]).TupleConcat(Array1[2][1]).TupleConcat(Array1[3][1]).TupleConcat(Array1[4][1]).TupleConcat(Array1[5][1]).TupleConcat(Array1[6][1]).TupleConcat(Array1[7][1]).TupleConcat(Array1[8][1]),
                                                        new HTuple(Array1[0][2]).TupleConcat(Array1[1][2]).TupleConcat(Array1[2][2]).TupleConcat(Array1[3][2]).TupleConcat(Array1[4][2]).TupleConcat(Array1[5][2]).TupleConcat(Array1[6][2]).TupleConcat(Array1[7][2]).TupleConcat(Array1[8][2]),
                                                        new HTuple(Array1[0][3]).TupleConcat(Array1[1][3]).TupleConcat(Array1[2][3]).TupleConcat(Array1[3][3]).TupleConcat(Array1[4][3]).TupleConcat(Array1[5][3]).TupleConcat(Array1[6][3]).TupleConcat(Array1[7][3]).TupleConcat(Array1[8][3])
                                                        , out var homMat2D);

                        HOperatorSet.WriteTuple(homMat2D, System.IO.Path.Combine(dirPath, "CalibHomMat2D.tup"));

                        HOperatorSet.VectorToHomMat2d(new HTuple(Array1[0][2]).TupleConcat(Array1[1][2]).TupleConcat(Array1[2][2]).TupleConcat(Array1[3][2]).TupleConcat(Array1[4][2]).TupleConcat(Array1[5][2]).TupleConcat(Array1[6][2]).TupleConcat(Array1[7][2]).TupleConcat(Array1[8][2]),
                                                  new HTuple(Array1[0][3]).TupleConcat(Array1[1][3]).TupleConcat(Array1[2][3]).TupleConcat(Array1[3][3]).TupleConcat(Array1[4][3]).TupleConcat(Array1[5][3]).TupleConcat(Array1[6][3]).TupleConcat(Array1[7][3]).TupleConcat(Array1[8][3]),
                                                  new HTuple(Array1[0][0]).TupleConcat(Array1[1][0]).TupleConcat(Array1[2][0]).TupleConcat(Array1[3][0]).TupleConcat(Array1[4][0]).TupleConcat(Array1[5][0]).TupleConcat(Array1[6][0]).TupleConcat(Array1[7][0]).TupleConcat(Array1[8][0]),
                                                  new HTuple(Array1[0][1]).TupleConcat(Array1[1][1]).TupleConcat(Array1[2][1]).TupleConcat(Array1[3][1]).TupleConcat(Array1[4][1]).TupleConcat(Array1[5][1]).TupleConcat(Array1[6][1]).TupleConcat(Array1[7][1]).TupleConcat(Array1[8][1])
                                                  , out var homMat2D1);

                        HOperatorSet.WriteTuple(homMat2D1, System.IO.Path.Combine(dirPath, "CalibHomMat2D_Rev.tup"));
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, "错误", MessageBoxButtons.OK);
                    }
                }
            }
            else
            {
                MessageBox.Show("图像不能为空", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
        async void ExecuteCameraOperateCommand(object obj)
        {
            if (obj is string str)
            {
                switch (str)
                {
                    case "打开":
                        {
                            Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog();
                            openFileDialog.Filter = "Image Files|*.png;*.bmp;*.jpg;*.tif";
                            if (openFileDialog.ShowDialog() == true)
                            {
                                HObject image;
                                HOperatorSet.ReadImage(out image, openFileDialog.FileName);
                                CameraImage0 = new HImage(image);
                            }
                        }
                        break;
                    case "拍照":
                        {
                            IHIKCameraService cameraService = leftCamera;
                            cameraService.ImageQueue.Clear();
                            cameraService.SetTriggerMode(0);
                            cameraService.SetExposureTime((float)CameraExposureTime);
                            cameraService.StartGrabe();
                            IsBusy = true;
                            bool breakFlag = false;
                            Task task = new Task(() => {
                                int mIndex = 0;
                                while (mIndex < 1 && !breakFlag)
                                {
                                    HObject? hObj;
                                    if (cameraService.ImageQueue.TryPeek(out hObj))
                                    {
                                        cameraService.ImageQueue.TryDequeue(out hObj);
                                        CameraImage0 = new HImage(hObj);
                                        mIndex++;
                                    }
                                }
                            });
                            task.Start();
                            var delay = Task.Delay(10000);
                            if (await Task.WhenAny(task, delay) == delay)
                            {
                                breakFlag = true;
                            }
                            cameraService.StopGrabe(); IsBusy = false;
                            if (breakFlag)
                            {
                                MessageBox.Show("拍照超时", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }
                        }
                        break;
                    default:
                        break;
                }
            }
        }
        #endregion
        #region 导航
        public override void OnDialogClosed()
        {
            if (source0 != null)
            {
                source0.Cancel();
            }
            if (source1 != null)
            {
                source1.Cancel();
            }
            IHIKCameraService cameraService = leftCamera;
            cameraService.StopGrabe();
            isClosing = true;
            if (IsDrawing)
            {
                MFunc.HIOCancelDraw();
            }
            CameraImage0 = null;
        }
        public override void OnDialogOpened(IDialogParameters parameters)
        {
            handIndex = parameters.GetValue<int>("HandIndex");

            switch (handIndex)
            {
                case 0:
                    Title = "Camera1";
                    handDir = "Camera1";
                    break;
                case 1:
                    Title = "Camera2";
                    handDir = "Camera2";
                    break;
                case 2:
                    Title = "Camera3";
                    handDir = "Camera3";
                    break;
                case 3:
                    Title = "Camera4";
                    handDir = "Camera4";
                    break;
                default:
                    break;
            }
            LoadParamFromDB();
            // Get the subdirectories for the specified directory.
            DirectoryInfo dir = new DirectoryInfo(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}"));
            if (!dir.Exists)
            {
                // If the destination directory doesn't exist, create it.       
                Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Camera\\Calib\\{handDir}"));
            }
        }
        #endregion
        #region 构造函数
        public CameraCalibDialogViewModel(IContainerProvider containerProvider) : base(containerProvider)
        {

            drawROI = containerProvider.Resolve<IDrawROI>("calibDrawROI");
            leftCamera = containerProvider.Resolve<IHIKCameraService>("LeftCamera");
            IsBusy = false;
            aggregator.ResgiterMessage(arg =>
            {
                switch (arg.Message)
                {
                    case "EMG":
                        {
                            if (source0 != null)
                            {
                                source0.Cancel();
                            }
                        }
                        break;
                    case "ReloadParam":
                    case "ChangePartNum":
                        LoadParamFromDB();
                        break;
                    default:
                        break;
                }
            }, "Run");
            aggregator.ResgiterMessage(arg => {
                var strs = arg.Message!.Split(new char[] { ';' });
                switch (strs[0])
                {
                    case "DisableEditParameter":
                        System.Windows.Application.Current.Dispatcher.Invoke(new Action(() =>
                        {
                            OnRequestClose(new Prism.Services.Dialogs.DialogResult(ButtonResult.No));
                        }));
                        break;
                    default:
                        break;
                }
            }, "Permissions");
        }
        #endregion
        #region 功能函数
        private void ContinueGrab(CancellationToken token)
        {
            IHIKCameraService cameraService = leftCamera;
            cameraService.ImageQueue.Clear();
            cameraService.SetTriggerMode(0);
            cameraService.SetExposureTime((float)CameraExposureTime);
            cameraService.StartGrabe();
            while (true)
            {
                if (token.IsCancellationRequested)
                {
                    cameraService.StopGrabe();
                    return;
                }
                HObject? hObj;
                if (cameraService.ImageQueue.TryPeek(out hObj))
                {
                    cameraService.ImageQueue.TryDequeue(out hObj);
                    CameraImage0 = new HImage(hObj);
                }
                System.Threading.Thread.Sleep(1);
            }
        }
        void LoadParamFromDB()
        {
            try
            {
                var mdb = containerProvider.Resolve<MDbContext>();
                LeftCameraCalibDist = Properties.Settings.Default.LeftCameraCalibDist;
                var _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "CameraExposureTime" && m.Hand == handIndex);
                if (_mParam != null)
                {
                    CameraExposureTime = double.Parse(_mParam.Value);
                }
                else
                {
                    CameraExposureTime = 200;
                    mdb.MParams.Add(new MParam()
                    {
                        Name = "CameraExposureTime",
                        Type = typeof(double).Name,
                        Value = CameraExposureTime.ToString("f1"),
                        Hand = handIndex
                    });
                    mdb.SaveChanges();
                }
                _mParam = mdb.MParams.FirstOrDefault(m => m.Name == "VxyLimit" && m.Hand == handIndex);
                if (_mParam != null)
                {
                    VxyLimit = double.Parse(_mParam.Value);
                }
                else
                {
                    VxyLimit = 2.1;
                    mdb.MParams.Add(new MParam()
                    {
                        Name = "VxyLimit",
                        Type = typeof(double).Name,
                        Value = CameraExposureTime.ToString("f1"),
                        Hand = handIndex
                    });
                    mdb.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                logger.Error(ex);
            }
        }

        #endregion
    }
    class OffsetPixel
    {
        public double Row0 { get; set; }
        public double Column0 { get; set; }
        public double Row1 { get; set; }
        public double Column1 { get; set; }
    }
}
